#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>

// 实现一个简易命令行解释器
#define NUM 1024
#define SIZE 32
#define SEP " "

// 用户输入的缓冲区
char cmd_line[NUM];
// 指针数据 保存打散之后的命令行字符串
char *g_argv[SIZE];
int main()
{
  // 首先是一个死循环
  while (1)
  {
    // 打印提示信息
    printf("[root@centos myshell]# ");
    fflush(stdout); // 刷新显示器

    // 首先初始化为\0
    memset(cmd_line, '\0', sizeof cmd_line);
    // 使用文件输入fgets函数
    if (fgets(cmd_line, sizeof cmd_line, stdin) == NULL) // 返回NULL说明报错了
    { continue; }  // 一般情况下是不会报错的 报错重新进行即可
    // 别忘了最后输入的是一个\n
    cmd_line[strlen(cmd_line) - 1] = '\0';

    // 将其分开 用指针数组进行
    // 使用函数 strtok(字符串, 分隔字符串);进行分隔 返回NULL表示无法分割了 返回第一个分隔字符串位置
    g_argv[0] = strtok(cmd_line, SEP);
    int index = 1;

    // 命令行处理函数 ls 加上 --color=auto
    if (strcmp(g_argv[0], "ls") == 0)
      g_argv[index++] = "--color=auto";
    while(g_argv[index - 1])
    {
      g_argv[index++] = strtok(NULL, SEP);  // 多次调用，解析历史字符串使用NULL确定
    }
    // 检查是否分割成功：
    //for (index = 0; g_argv[index]; ++index)
    //{
    //  printf("%s\n", g_argv[index]);
    //}
    
    // 判断是否要内部执行函数，cd的话调用子进程没有用，需要myshell进程也就是父进程切换目录才有效
    if (strcmp(g_argv[0], "cd") == 0)
    {
      // int chdir(char* path) 切换当前工作目录
      if (g_argv[1] != NULL)  chdir(g_argv[1]);
    }
    else 
    {
      // 创建子进程
      pid_t id = fork();
      if (id == 0)
      {
        // child
        // 使用替换函数 execvp 
        execvp(g_argv[0], g_argv);
        exit(1);
      }
      // father
     int status = 0;   // 接收返回码
     pid_t ret = waitpid(id, &status, 0);  // 阻塞等待
     if (ret > 0)
       printf("exit code:%d\n", WEXITSTATUS(status));
    }
  }
  return 0;
}
